﻿#include "NPCDialogs.h"
#include "../../MirGraphics/MLibrary.h"
#include "../../MirSounds/SoundManager.h"
#include "../../MirControls/MirAnimatedButton.h"
#include "../../Forms/Client.CMain.h"
#include "../../../Shared/Functions/Functions.h"
#include "../../MirObjects/NPCObject.h"
#include "../GameScene.h"
#include "../../../Shared/Language.h"
#include "../../MirObjects/MapObject.h"
#include "../../MirControls/MirAmountBox.h"
#include "../../../Shared/Data/Stat.h"
#include "../../../Shared/ClientPackets.h"
#include "../../MirNetwork/Network.h"
#include "../../../Shared/Globals.h"
#include "../../MirObjects/UserObject.h"

using namespace Client::MirControls;
using namespace Client::MirGraphics;
using namespace Client::MirNetwork;
using namespace Client::MirObjects;
using namespace Client::MirSounds;
namespace S = ServerPackets;
namespace C = ClientPackets;
using Effect = Client::MirObjects::Effect;
using namespace Client::MirScenes::Dialogs;

namespace Client::MirScenes::Dialogs
{

Regex *NPCDialog::R = new Regex(R"(<((.*?)\/(\@.*?))>)");
Regex *NPCDialog::C = new Regex(R"({((.*?)\/(.*?))})");
Regex *NPCDialog::L = new Regex(R"(\(((.*?)\/(.*?))\))");

    NPCDialog::NPCDialog()
    {
        setIndex(995);
        setLibrary(Libraries::Prguse);

        TextLabel = std::vector<MirLabel*>(30);
        TextButtons = std::vector<MirLabel*>();

        MouseWheel += NPCDialog_MouseWheel;

        setSort(true);

        NameLabel = new MirLabel();
        NameLabel->setText("");
        NameLabel->setParent(this);
        System::Drawing::Font tempVar(Settings::FontName, 10.0F, FontStyle::Bold);
        NameLabel->setFont(&tempVar);
        NameLabel->setForeColour(Color::BurlyWood);
        Point tempVar2(30, 6);
        NameLabel->setLocation(&tempVar2);
        NameLabel->setAutoSize(true);

        UpButton = new MirButton();
        UpButton->setIndex(197);
        UpButton->setHoverIndex(198);
        UpButton->setPressedIndex(199);
        UpButton->setLibrary(Libraries::Prguse2);
        UpButton->setParent(this);
        Size tempVar3(16, 14);
        UpButton->setSize(&tempVar3);
        Point tempVar4(417, 34);
        UpButton->setLocation(&tempVar4);
        UpButton->setSound(SoundList::ButtonA);
        UpButton->setVisible(false);
        UpButton->Click += [&] (o, e)
        {
            if (_index <= 0)
            {
                return;
            }
    
            _index--;
    
            NewText(CurrentLines, false);
            UpdatePositionBar();
        };

        DownButton = new MirButton();
        DownButton->setIndex(207);
        DownButton->setHoverIndex(208);
        DownButton->setLibrary(Libraries::Prguse2);
        DownButton->setPressedIndex(209);
        DownButton->setParent(this);
        Size tempVar5(16, 14);
        DownButton->setSize(&tempVar5);
        Point tempVar6(417, 175);
        DownButton->setLocation(&tempVar6);
        DownButton->setSound(SoundList::ButtonA);
        DownButton->setVisible(false);
        DownButton->Click += [&] (o, e)
        {
            if (_index + MaximumLines >= CurrentLines.size())
            {
                return;
            }
    
            _index++;
    
            NewText(CurrentLines, false);
            UpdatePositionBar();
        };

        PositionBar = new MirButton();
        PositionBar->setIndex(205);
        PositionBar->setHoverIndex(206);
        PositionBar->setPressedIndex(206);
        PositionBar->setLibrary(Libraries::Prguse2);
        Point tempVar7(417, 47);
        PositionBar->setLocation(&tempVar7);
        PositionBar->setParent(this);
        PositionBar->setMovable(true);
        PositionBar->setSound(SoundList::None);
        PositionBar->setVisible(false);
        PositionBar->OnMoving->addListener("PositionBar_OnMoving", std::bind(&NPCDialog::PositionBar_OnMoving, this, std::placeholders::_1, std::placeholders::_2));

        QuestButton = new MirAnimatedButton();
        QuestButton->Animated = true;
        QuestButton->AnimationCount = 10;
        QuestButton->Loop = true;
        QuestButton->AnimationDelay = 130;
        QuestButton->setIndex(530);
        QuestButton->setHoverIndex(284);
        QuestButton->setPressedIndex(286);
        QuestButton->setLibrary(Libraries::Title);
        QuestButton->setParent(this);
        Size tempVar8(96, 25);
        QuestButton->setSize(&tempVar8);
        Point tempVar9((440 - 96) / 2, 224 - 30);
        QuestButton->setLocation(&tempVar9);
        QuestButton->setSound(SoundList::ButtonA);
        QuestButton->setVisible(false);

        QuestButton->Click += [&] (o, e)
        {
            GameScene::Scene->QuestListDialog->Toggle();
        };

        CloseButton = new MirButton();
        CloseButton->setHoverIndex(361);
        CloseButton->setIndex(360);
        Point tempVar10(413, 3);
        CloseButton->setLocation(&tempVar10);
        CloseButton->setLibrary(Libraries::Prguse2);
        CloseButton->setParent(this);
        CloseButton->setPressedIndex(362);
        CloseButton->setSound(SoundList::ButtonA);
        CloseButton->Click += [&] (o, e)
        {
            Hide();
        };

        MirButton *helpButton = new MirButton();
        helpButton->setIndex(257);
        helpButton->setHoverIndex(258);
        helpButton->setPressedIndex(259);
        helpButton->setLibrary(Libraries::Prguse2);
        helpButton->setParent(this);
        Point tempVar11(390, 3);
        helpButton->setLocation(&tempVar11);
        helpButton->setSound(SoundList::ButtonA);
        helpButton->Click += [&] (o, e)
        {
            GameScene::Scene->HelpDialog->DisplayPage("Purchasing");
        };

        delete helpButton;
    }

    void NPCDialog::NPCDialog_MouseWheel(std::any sender, MouseEventArgs *e)
    {
        int count = e->Delta / SystemInformation::MouseWheelScrollDelta;

        if (_index == 0 && count >= 0)
        {
            return;
        }
        if (_index == CurrentLines.size() - 1 && count <= 0)
        {
            return;
        }
        if (CurrentLines.size() <= MaximumLines)
        {
            return;
        }

        _index -= count;

        if (_index < 0)
        {
            _index = 0;
        }
        if (_index + MaximumLines > CurrentLines.size() - 1)
        {
            _index = CurrentLines.size() - MaximumLines;
        }

        NewText(CurrentLines, false);

        UpdatePositionBar();
    }

    void NPCDialog::PositionBar_OnMoving(std::any sender, MouseEventArgs *e)
    {
        int x = 417;
        int y = PositionBar->getLocation()->Y;

        if (y >= 155)
        {
            y = 155;
        }
        if (y <= 47)
        {
            y = 47;
        }

        int location = y - 47;
        int interval = 108 / (CurrentLines.size() - MaximumLines);

        double yPoint = location / interval;

        _index = static_cast<short>(std::floor(yPoint));

        NewText(CurrentLines, false);

        Point tempVar(x, y);
        PositionBar->setLocation(&tempVar);
    }

    void NPCDialog::UpdatePositionBar()
    {
        if (CurrentLines.size() <= MaximumLines)
        {
            return;
        }

        int interval = 108 / (CurrentLines.size() - MaximumLines);

        int x = 417;
        int y = 48 + (_index * interval);

        if (y >= 155)
        {
            y = 155;
        }
        if (y <= 47)
        {
            y = 47;
        }

        Point tempVar(x, y);
        PositionBar->setLocation(&tempVar);
    }

    void NPCDialog::NewText(std::vector<std::string> &lines, bool resetIndex)
    {
        if (resetIndex)
        {
            _index = 0;
            CurrentLines = lines;
            UpdatePositionBar();
        }

        if (lines.size() > MaximumLines)
        {
            setIndex(385);
            UpButton->setVisible(true);
            DownButton->setVisible(true);
            PositionBar->setVisible(true);
        }
        else
        {
            setIndex(384);
            UpButton->setVisible(false);
            DownButton->setVisible(false);
            PositionBar->setVisible(false);
        }

        for (int i = 0; i < TextButtons.size(); i++)
        {
            TextButtons[i]->Dispose();
        }

        for (int i = 0; i < TextLabel.size(); i++)
        {
            if (TextLabel[i] != nullptr)
            {
                TextLabel[i]->setText("");
            }
        }

        TextButtons.clear();

        int lastLine = lines.size() > MaximumLines ? ((MaximumLines + _index) > lines.size() ? lines.size() : (MaximumLines + _index)) : lines.size();

        for (int i = _index; i < lastLine; i++)
        {
            MirLabel *tempVar = new MirLabel();
            tempVar->setFont(font);
            tempVar->setDrawFormat(TextFormatFlags::WordBreak);
            tempVar->setVisible(true);
            tempVar->setParent(this);
            Size tempVar2(420, 20);
            tempVar->setSize(&tempVar2);
            Point tempVar3(20, 34 + (i - _index) * 20);
            tempVar->setLocation(&tempVar3);
            tempVar->setNotControl(true);
            TextLabel[i] = tempVar;

            if (i >= lines.size())
            {
                TextLabel[i]->setText("");

                delete tempVar;
                continue;
            }

            std::string currentLine = lines[i];

            std::vector<Match*> matchList = R->Matches(currentLine)->Cast<Match*>().ToList();
            matchList.AddRange(C->Matches(currentLine)->Cast<Match*>());
            matchList.AddRange(L->Matches(currentLine)->Cast<Match*>());

            int oldLength = currentLine.length();

            for (auto match : matchList.OrderBy([&] (std::any o)
            {
                return o::Index;
            }).ToList())
            {
                int offSet = oldLength - currentLine.length();

                Capture *capture = match::Groups[1].Captures[0];
                std::string txt = match::Groups[2].Captures[0]->Value;
                std::string action = match::Groups[3].Captures[0]->Value;

//C# TO C++ CONVERTER TODO TASK: There is no C++ equivalent to the .NET String 'Insert' method unless assigning to the string instance:
                currentLine.erase(capture->Index - 1 - offSet, capture->Length + 2)->Insert(capture->Index - 1 - offSet, txt);
                std::string text = currentLine.substr(0, capture->Index - 1 - offSet) + " ";
                Size *size = TextRenderer::MeasureText(CMain::Graphics, text, TextLabel[i]->getFont(), TextLabel[i]->getSize(), TextFormatFlags::TextBoxControl);

                if (R->Match(match->Value)->Success)
                {
                    Point tempVar4(size->Width - 10, 0);
                    NewButton(txt, action, Functions::Add(TextLabel[i]->getLocation(), &tempVar4));
                }

                if (C->Match(match->Value)->Success)
                {
                    Point tempVar5(size->Width - 10, 0);
                    NewColour(txt, action, Functions::Add(TextLabel[i]->getLocation(), &tempVar5));
                }

                if (L->Match(match->Value)->Success)
                {
                    Point tempVar6(size->Width - 10, 0);
                    NewButton(txt, "", Functions::Add(TextLabel[i]->getLocation(), &tempVar6), action);
                }
            }

            TextLabel[i]->setText(currentLine);
            TextLabel[i]->MouseWheel += NPCDialog_MouseWheel;

            delete tempVar;
        }
    }

    void NPCDialog::NewButton(const std::string &text, const std::string &key, Point *p, const std::string &link)
    {
        MirLabel *temp = new MirLabel();
        temp->setAutoSize(true);
        temp->setVisible(true);
        temp->setParent(this);
        temp->setLocation(p);
        temp->setText(text);
        temp->setForeColour(Color::Yellow);
        temp->setSound(SoundList::ButtonC);
        temp->setFont(font);

        temp->MouseEnter += [&] (o, e)
        {
            temp->setForeColour(Color::Red);
        };
        temp->MouseLeave += [&] (o, e)
        {
            temp->setForeColour(Color::Yellow);
        };
        temp->MouseDown += [&] (o, e)
        {
            temp->setForeColour(Color::Yellow);
        };
        temp->MouseUp->addListener([&] (o, e)
        {
            temp->setForeColour(Color::Red);
        });

        if (!link.empty())
        {
            temp->Click += [&] (o, e)
            {
                if (link.StartsWith("http://", true, CultureInfo::InvariantCulture))
                {
                    System::Diagnostics::Process::Start(link);
                }
            };
        }
        else
        {
            temp->Click += [&] (o, e)
            {
                if (key == "[@Exit]")
                {
                    Hide();
                    return;
                }
    
                if (CMain::Time <= GameScene::NPCTime)
                {
                    return;
                }
    
                GameScene::NPCTime = CMain::Time + 5000;
                C::CallNPC *tempVar = new C::CallNPC();
                tempVar->ObjectID = GameScene::NPCID;
                tempVar->Key = StringHelper::formatSimple("[{0}]", key);
                Network::Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            };
        }

        temp->MouseWheel += NPCDialog_MouseWheel;

        TextButtons.push_back(temp);

//C# TO C++ CONVERTER TODO TASK: A 'delete temp' statement was not added since temp was passed to a method or constructor. Handle memory management manually.
    }

    void NPCDialog::NewColour(const std::string &text, const std::string &colour, Point *p)
    {
        Color *textColour = Color::FromName(colour);

        MirLabel *temp = new MirLabel();
        temp->setAutoSize(true);
        temp->setVisible(true);
        temp->setParent(this);
        temp->setLocation(p);
        temp->setText(text);
        temp->setForeColour(textColour);
        temp->setFont(font);
        temp->MouseWheel += NPCDialog_MouseWheel;

        TextButtons.push_back(temp);

//C# TO C++ CONVERTER TODO TASK: A 'delete temp' statement was not added since temp was passed to a method or constructor. Handle memory management manually.
    }

    void NPCDialog::CheckQuestButtonDisplay()
    {
        NameLabel->setText("");

        QuestButton->setVisible(false);

        NPCObject *npc = static_cast<NPCObject*>(MapControl::GetObject(GameScene::NPCID));
        if (npc != nullptr)
        {
            std::vector<std::string> nameSplit = StringHelper::split(npc->Name, '_');
            NameLabel->setText(nameSplit[0]);

            if (npc->GetAvailableQuests().Any())
            {
                QuestButton->setVisible(true);
            }
        }
    }

    void NPCDialog::Hide()
    {
        setVisible(false);
        GameScene::Scene->NPCGoodsDialog->Hide();
        GameScene::Scene->NPCSubGoodsDialog->Hide();
        GameScene::Scene->NPCCraftGoodsDialog->Hide();
        GameScene::Scene->NPCDropDialog->Hide();
        GameScene::Scene->NPCAwakeDialog->Hide();
        GameScene::Scene->RefineDialog->Hide();
        GameScene::Scene->StorageDialog->Hide();
        GameScene::Scene->TrustMerchantDialog->Hide();
        GameScene::Scene->QuestListDialog->Hide();
        Point tempVar(0, 0);
        GameScene::Scene->InventoryDialog->setLocation(&tempVar);
    }

    void NPCDialog::Show()
    {
        Point tempVar(getSize()->Width + 5, 0);
        GameScene::Scene->InventoryDialog->setLocation(&tempVar);
        setVisible(true);

        CheckQuestButtonDisplay();
    }

    NPCGoodsDialog::NPCGoodsDialog(PanelType type)
    {
        PType = type;

        setIndex(1000);
        setLibrary(Libraries::Prguse);
        Point tempVar(0, 224);
        setLocation(&tempVar);
        Cells = std::vector<MirGoodsCell*>(8);
        setSort(true);

        for (int i = 0; i < Cells.size(); i++)
        {
            MirGoodsCell *tempVar2 = new MirGoodsCell();
            tempVar2->setParent(this);
            Point tempVar3(10, 34 + i * 33);
            tempVar2->setLocation(&tempVar3);
            tempVar2->setSound(SoundList::ButtonC);
            Cells[i] = tempVar2;
            Cells[i]->Click += [&] (o, e)
            {
                SelectedItem = (static_cast<MirGoodsCell*>(o))->Item;
                Update();
    
                if (PType == PanelType::Craft)
                {
                    GameScene::Scene->CraftDialog->ResetCells();
                    GameScene::Scene->CraftDialog->RefreshCraftCells(SelectedItem);
    
                    if (!GameScene::Scene->CraftDialog->getVisible())
                    {
                        GameScene::Scene->CraftDialog->Show();
                    }
                }
            };
            Cells[i]->MouseWheel += NPCGoodsPanel_MouseWheel;
            Cells[i]->DoubleClick += [&] (o, e)
            {
                if (PType == PanelType::Craft)
                {
                    return;
                }
    
                BuyItem();
            };

            delete tempVar2;
        }

        CloseButton = new MirButton();
        CloseButton->setHoverIndex(361);
        CloseButton->setIndex(360);
        Point tempVar4(217, 3);
        CloseButton->setLocation(&tempVar4);
        CloseButton->setLibrary(Libraries::Prguse2);
        CloseButton->setParent(this);
        CloseButton->setPressedIndex(362);
        CloseButton->setSound(SoundList::ButtonA);
        CloseButton->Click += [&] (o, e)
        {
            Hide();
        };

        BuyButton = new MirButton();
        BuyButton->setHoverIndex(313);
        BuyButton->setIndex(312);
        Point tempVar5(77, 304);
        BuyButton->setLocation(&tempVar5);
        BuyButton->setLibrary(Libraries::Title);
        BuyButton->setParent(this);
        BuyButton->setPressedIndex(314);
        BuyButton->setSound(SoundList::ButtonA);
        BuyButton->Click += [&] (o, e)
        {
            BuyItem();
        };

        BuyLabel = new MirImageControl();
        BuyLabel->setIndex(27);
        BuyLabel->setLibrary(Libraries::Title);
        BuyLabel->setParent(this);
        Point tempVar6(20, 9);
        BuyLabel->setLocation(&tempVar6);

        if (PType == PanelType::Craft)
        {
            BuyLabel->setIndex(12);
            BuyButton->setVisible(false);
        }

        UpButton = new MirButton();
        UpButton->setIndex(197);
        UpButton->setHoverIndex(198);
        UpButton->setLibrary(Libraries::Prguse2);
        Point tempVar7(219, 35);
        UpButton->setLocation(&tempVar7);
        UpButton->setParent(this);
        UpButton->setPressedIndex(199);
        UpButton->setSound(SoundList::ButtonA);
        UpButton->Click += [&] (o, e)
        {
            if (StartIndex == 0)
            {
                return;
            }
            StartIndex--;
            Update();
        };

        DownButton = new MirButton();
        DownButton->setIndex(207);
        DownButton->setHoverIndex(208);
        DownButton->setLibrary(Libraries::Prguse2);
        Point tempVar8(219, 284);
        DownButton->setLocation(&tempVar8);
        DownButton->setParent(this);
        DownButton->setPressedIndex(209);
        DownButton->setSound(SoundList::ButtonA);
        DownButton->Click += [&] (o, e)
        {
            if (DisplayGoods.size() <= 8)
            {
                return;
            }
    
            if (StartIndex == DisplayGoods.size() - 8)
            {
                return;
            }
            StartIndex++;
            Update();
        };

        PositionBar = new MirButton();
        PositionBar->setIndex(205);
        PositionBar->setHoverIndex(206);
        PositionBar->setLibrary(Libraries::Prguse2);
        Point tempVar9(219, 49);
        PositionBar->setLocation(&tempVar9);
        PositionBar->setParent(this);
        PositionBar->setPressedIndex(206);
        PositionBar->setMovable(true);
        PositionBar->setSound(SoundList::None);
        PositionBar->OnMoving->addListener("PositionBar_OnMoving", std::bind(&NPCGoodsDialog::PositionBar_OnMoving, this, std::placeholders::_1, std::placeholders::_2));
        PositionBar->MouseUp->addListener([&] (o, e)
        {
            Update();
        });
    }

    bool NPCGoodsDialog::CheckSubGoods()
    {
        if (SelectedItem == nullptr)
        {
            return false;
        }

        if (PType == PanelType::Buy && !UsePearls)
        {
            auto list = Goods.Where([&] (std::any x)
            {
                return x::Info->Index == SelectedItem->Info->Index;
            }).ToList();

            if (list.size() > 1 || GameScene::Scene->NPCSubGoodsDialog->getVisible())
            {
                GameScene::Scene->NPCSubGoodsDialog->NewGoods(list);
                GameScene::Scene->NPCSubGoodsDialog->Show();
                return true;
            }
        }

        return false;
    }

    void NPCGoodsDialog::BuyItem()
    {
        if (SelectedItem == nullptr)
        {
            return;
        }

        if (CheckSubGoods())
        {
            return;
        }

        if (SelectedItem->Info->StackSize > 1)
        {
            unsigned short tempCount = SelectedItem->Count;
            unsigned short maxQuantity = SelectedItem->Info->StackSize;

            SelectedItem->Count = maxQuantity;

            if (UsePearls)
            {
                if (SelectedItem->Price() > GameScene::getUser()->PearlCount)
                {
                    maxQuantity = std::min(std::numeric_limits<unsigned short>::max(), static_cast<unsigned short>(GameScene::Gold / (SelectedItem->Price() / SelectedItem->Count)));
                    if (maxQuantity == 0)
                    {
                        GameScene::Scene->ChatDialog->ReceiveChat("You do not have enough Pearls.", ChatType::System);
                        return;
                    }
                }
            }

            else if (SelectedItem->Price() > GameScene::Gold)
            {
                maxQuantity = std::min(std::numeric_limits<unsigned short>::max(), static_cast<unsigned short>(GameScene::Gold / (SelectedItem->Price() / SelectedItem->Count)));
                if (maxQuantity == 0)
                {
                    GameScene::Scene->ChatDialog->ReceiveChat(GameLanguage::LowGold, ChatType::System);
                    return;
                }
            }

            MapObject::User->GetMaxGain(SelectedItem);

            if (SelectedItem->Count > tempCount)
            {
                SelectedItem->Count = tempCount;
            }

            if (SelectedItem->Count == 0)
            {
                return;
            }

            MirAmountBox *amountBox = new MirAmountBox("Purchase Amount:", SelectedItem->getImage(), maxQuantity, 0, SelectedItem->Count);

            amountBox->OKButton->Click += [&] (o, e)
            {
                if (amountBox->Amount > 0)
                {
                    C::BuyItem *tempVar = new C::BuyItem();
                    tempVar->ItemIndex = SelectedItem->UniqueID;
                    tempVar->Count = static_cast<unsigned short>(amountBox->Amount);
                    tempVar->Type = PanelType::Buy;
                    Network::Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
                }
            };

            amountBox->Show();

            delete amountBox;
        }
        else
        {
            if (SelectedItem->Info->Price > GameScene::Gold)
            {
                GameScene::Scene->ChatDialog->ReceiveChat(GameLanguage::LowGold, ChatType::System);
                return;
            }

            if (SelectedItem->getWeight() > (MapObject::User->Stats[Stat::BagWeight] - MapObject::User->CurrentBagWeight))
            {
                GameScene::Scene->ChatDialog->ReceiveChat("You do not have enough weight.", ChatType::System);
                return;
            }

            for (int i = 0; i < MapObject::User->Inventory.size(); i++)
            {
                if (MapObject::User->Inventory[i] == nullptr)
                {
                    break;
                }
                if (i == MapObject::User->Inventory.size() - 1)
                {
                    GameScene::Scene->ChatDialog->ReceiveChat("You cannot purchase any more items.", ChatType::System);
                    return;
                }
            }

            C::BuyItem *tempVar2 = new C::BuyItem();
            tempVar2->ItemIndex = SelectedItem->UniqueID;
            tempVar2->Count = 1;
            tempVar2->Type = PanelType::Buy;
            Network::Enqueue(tempVar2);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
        }
    }

    void NPCGoodsDialog::NPCGoodsPanel_MouseWheel(std::any sender, MouseEventArgs *e)
    {
        int count = e->Delta / SystemInformation::MouseWheelScrollDelta;

        if (StartIndex == 0 && count >= 0)
        {
            return;
        }
        if (StartIndex == DisplayGoods.size() - 1 && count <= 0)
        {
            return;
        }

        StartIndex -= count;
        Update();
    }

    void NPCGoodsDialog::Update()
    {
        if (StartIndex > DisplayGoods.size() - 8)
        {
            StartIndex = DisplayGoods.size() - 8;
        }
        if (StartIndex <= 0)
        {
            StartIndex = 0;
        }

        if (DisplayGoods.size() > 8)
        {
            PositionBar->setVisible(true);
            int h = 233 - PositionBar->getSize()->Height;
            h = static_cast<int>((h / static_cast<float>(DisplayGoods.size() - 8)) * StartIndex);
            Point tempVar(219, 49 + h);
            PositionBar->setLocation(&tempVar);
        }
        else
        {
            PositionBar->setVisible(false);
        }


        for (int i = 0; i < 8; i++)
        {
            if (i + StartIndex >= DisplayGoods.size())
            {
                Cells[i]->setVisible(false);
                continue;
            }
            Cells[i]->setVisible(true);

            auto matchingGoods = Goods.Where([&] (std::any x)
            {
                return x::Info->Index == Cells[i]->Item->Info.Index;
            });

            Cells[i]->Item = DisplayGoods[i + StartIndex];
            Cells[i]->MultipleAvailable = matchingGoods->Count() > 1 && matchingGoods->Any([&] (std::any x)
            {
                return x->IsShopItem == false;
            });
            Cells[i]->setBorder(SelectedItem != nullptr && Cells[i]->Item == SelectedItem);
            Cells[i]->UsePearls = UsePearls;
        }
    }

    void NPCGoodsDialog::PositionBar_OnMoving(std::any sender, MouseEventArgs *e)
    {
        constexpr int x = 219;
        int y = PositionBar->getLocation()->Y;
        if (y >= 282 - PositionBar->getSize()->Height)
        {
            y = 282 - PositionBar->getSize()->Height;
        }
        if (y < 49)
        {
            y = 49;
        }

        int h = 233 - PositionBar->getSize()->Height;
        h = static_cast<int>(BankersRounding::round(((y - 49) / (h / static_cast<float>(DisplayGoods.size() - 8)))));

        Point tempVar(x, y);
        PositionBar->setLocation(&tempVar);

        if (h == StartIndex)
        {
            return;
        }
        StartIndex = h;
        Update();
    }

    void NPCGoodsDialog::NewGoods(std::vector<UserItem*> &list)
    {
        Goods.clear();
        DisplayGoods.clear();

        if (PType == PanelType::BuySub)
        {
            StartIndex = 0;
            SelectedItem = nullptr;

            list = list.OrderBy([&] (std::any x)
            {
                x::Price();
            });
        }

        for (auto item : list)
        {
            //Normal shops just want to show one of each item type
            if (PType == PanelType::Buy && !UsePearls)
            {
                Goods.push_back(item);

                if (DisplayGoods.Any([&] (std::any x)
                {
                    return x::Info->Index == item->Info->Index;
                }))
                {
                    continue;
                }
            }

            DisplayGoods.push_back(item);
        }

        if (GameScene::Scene->NPCSubGoodsDialog->getVisible())
        {
            CheckSubGoods();
        }

        Update();
    }

    void NPCGoodsDialog::Hide()
    {
        setVisible(false);

        if (GameScene::Scene->CraftDialog->getVisible())
        {
            GameScene::Scene->CraftDialog->Hide();
        }
    }

    void NPCGoodsDialog::Show()
    {
        for (int i = 0; i < Cells.size(); i++)
        {
            Cells[i]->Recipe = PType == PanelType::Craft;
        }

        setVisible(true);

        GameScene::Scene->InventoryDialog->Show();
    }

UserItem *NPCDropDialog::TargetItem;

    NPCDropDialog::NPCDropDialog() : ConfirmButton(new MirButton();
        ConfirmButton->setHoverIndex(291);
        ConfirmButton->setIndex(290);
        Point tempVar(114, 62);
        ConfirmButton->setLocation(&tempVar);
        ConfirmButton->setLibrary(Libraries::Title);
        ConfirmButton->setParent(this);
        ConfirmButton->setPressedIndex(292);
        ConfirmButton->setSound(SoundList::ButtonA)), HoldButton(new MirButton();
        HoldButton->setHoverIndex(294);
        HoldButton->setIndex(293);
        Point tempVar2(114, 36);
        HoldButton->setLocation(&tempVar2);
        HoldButton->setLibrary(Libraries::Title);
        HoldButton->setParent(this);
        HoldButton->setPressedIndex(295);
        HoldButton->setSound(SoundList::ButtonA)), ItemCell(new MirItemCell();
        ItemCell->setBorderColour(Color::Lime);
        ItemCell->setGridType(MirGridType::DropPanel);
        ItemCell->setLibrary(Libraries::Items);
        ItemCell->setParent(this);
        Point tempVar3(38, 72);
        ItemCell->setLocation(&tempVar3)), InfoLabel(new MirLabel();
        InfoLabel->setAutoSize(true);
        Point tempVar4(30, 10);
        InfoLabel->setLocation(&tempVar4);
        InfoLabel->setParent(this);
        InfoLabel->setNotControl(true))
        {
        setIndex(392);
        setLibrary(Libraries::Prguse);
        Point tempVar5(264, 224);
        setLocation(&tempVar5);
        setSort(true);

        Click += NPCDropPanel_Click;

        HoldButton->Click += [&] (o, e)
        {
            Hold = !Hold;
        };

        ConfirmButton->Click += [&] (o, e)
        {
            Confirm();
        };


        ItemCell->Click += [&] (o, e)
        {
            ItemCell_Click();
        };

        BeforeDraw += NPCDropPanel_BeforeDraw;
        AfterDraw += NPCDropPanel_AfterDraw;
        }

    void NPCDropDialog::NPCDropPanel_AfterDraw(std::any sender, EventArgs *e)
    {
        if (Hold)
        {
            Libraries::Title->Draw(295, 114 + getDisplayLocation()->X, 36 + getDisplayLocation()->Y);
        }
    }

    void NPCDropDialog::NPCDropPanel_Click(std::any sender, EventArgs *e)
    {
        MouseEventArgs *me = dynamic_cast<MouseEventArgs*>(e);

        if (me == nullptr)
        {
            return;
        }
        int x = me->X - getDisplayLocation()->X;
        int y = me->Y - getDisplayLocation()->Y;

        Rectangle tempVar(20, 55, 75, 75);
        if ((&tempVar)->Contains(x, y))
        {
            ItemCell_Click();
        }
    }

    void NPCDropDialog::Confirm()
    {
        if (TargetItem == nullptr)
        {
            return;
        }

        switch (PType)
        {
            case PanelType::Sell:
                if (TargetItem->Info->Bind::HasFlag(BindMode::DontSell))
                {
                    GameScene::Scene->ChatDialog->ReceiveChat("Cannot sell this item.", ChatType::System);
                    return;
                }
                if (GameScene::Gold + TargetItem->Price() / 2 <= std::numeric_limits<unsigned int>::max())
                {
                    C::SellItem *tempVar = new C::SellItem();
                    tempVar->UniqueID = TargetItem->UniqueID;
                    tempVar->Count = TargetItem->Count;
                    Network::Enqueue(tempVar);
                    TargetItem = nullptr;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
                    return;
                }
                GameScene::Scene->ChatDialog->ReceiveChat("Cannot carry anymore gold.", ChatType::System);
                break;
            case PanelType::Repair:
                if (TargetItem->Info->Bind::HasFlag(BindMode::DontRepair))
                {
                    GameScene::Scene->ChatDialog->ReceiveChat("Cannot repair this item.", ChatType::System);
                    return;
                }
                if (GameScene::Gold >= TargetItem->RepairPrice() * GameScene::NPCRate)
                {
                    C::RepairItem *tempVar2 = new C::RepairItem();
                    tempVar2->UniqueID = TargetItem->UniqueID;
                    Network::Enqueue(tempVar2);
                    TargetItem = nullptr;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
                    return;
                }
                GameScene::Scene->ChatDialog->ReceiveChat(GameLanguage::LowGold, ChatType::System);
                break;
            case PanelType::SpecialRepair:
                if ((TargetItem->Info->Bind::HasFlag(BindMode::DontRepair)) || (TargetItem->Info->Bind::HasFlag(BindMode::NoSRepair)))
                {
                    GameScene::Scene->ChatDialog->ReceiveChat("Cannot repair this item.", ChatType::System);
                    return;
                }
                if (GameScene::Gold >= (TargetItem->RepairPrice() * 3) * GameScene::NPCRate)
                {
                    C::SRepairItem *tempVar3 = new C::SRepairItem();
                    tempVar3->UniqueID = TargetItem->UniqueID;
                    Network::Enqueue(tempVar3);
                    TargetItem = nullptr;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar3' statement was not added since tempVar3 was passed to a method or constructor. Handle memory management manually.
                    return;
                }
                GameScene::Scene->ChatDialog->ReceiveChat(GameLanguage::LowGold, ChatType::System);
                break;
            case PanelType::Consign:
            {
                if (TargetItem->Info->Bind::HasFlag(BindMode::DontStore) || TargetItem->Info->Bind::HasFlag(BindMode::DontSell))
                {
                    GameScene::Scene->ChatDialog->ReceiveChat("Cannot consign this item.", ChatType::System);
                    return;
                }
                MirAmountBox *box = new MirAmountBox("Consignment Price:", TargetItem->getImage(), Globals::MaxConsignment, Globals::MinConsignment);
                box->InputTextBox = {Text = ""};
                box->Amount = 0;

                box->Show();
                box->OKButton->Click += [&] (o, e)
                {
                    C::ConsignItem *tempVar4 = new C::ConsignItem();
                    tempVar4->UniqueID = TargetItem->UniqueID;
                    tempVar4->Price = box->Amount;
                    tempVar4->Type = MarketPanelType::Consign;
                    Network::Enqueue(tempVar4);
                    TargetItem = nullptr;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar4' statement was not added since tempVar4 was passed to a method or constructor. Handle memory management manually.
                };

                delete box;
                return;
            }
            case PanelType::Disassemble:
                C::DisassembleItem *tempVar5 = new C::DisassembleItem();
                tempVar5->UniqueID = TargetItem->UniqueID;
                Network::Enqueue(tempVar5);
                break;
            case PanelType::Downgrade:
                C::DowngradeAwakening *tempVar6 = new C::DowngradeAwakening();
                tempVar6->UniqueID = TargetItem->UniqueID;
                Network::Enqueue(tempVar6);
                break;
            case PanelType::Reset:
                if (TargetItem->Info->NeedIdentify == false)
                {
                    C::ResetAddedItem *tempVar7 = new C::ResetAddedItem();
                    tempVar7->UniqueID = TargetItem->UniqueID;
                    Network::Enqueue(tempVar7);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar7' statement was not added since tempVar7 was passed to a method or constructor. Handle memory management manually.
                }
                break;
            case PanelType::Refine:

                for (int i = 0; i < GameScene::Scene->RefineDialog->Grid.size(); i++)
                {
                    if (GameScene::Scene->RefineDialog->Grid[i]->getItem() != nullptr)
                    {
                        if (GameScene::Gold >= ((TargetItem->Info->RequiredAmount * 10) * GameScene::NPCRate))
                        {
                            C::RefineItem *tempVar8 = new C::RefineItem();
                            tempVar8->UniqueID = TargetItem->UniqueID;
                            Network::Enqueue(tempVar8);
                            TargetItem = nullptr;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar8' statement was not added since tempVar8 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar5' statement was not added since tempVar5 was passed to a method or constructor. Handle memory management manually.
                            return;
                        }
                        GameScene::Scene->ChatDialog->ReceiveChat(StringHelper::formatSimple("You don't have enough gold to refine your {0}.", TargetItem->getFriendlyName()), ChatType::System);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar5' statement was not added since tempVar5 was passed to a method or constructor. Handle memory management manually.
                        return;
                    }

                }
                GameScene::Scene->ChatDialog->ReceiveChat(StringHelper::formatSimple("You haven't deposited any items to refine your {0} with.", TargetItem->getFriendlyName()), ChatType::System);
                break;
            case PanelType::CheckRefine:

                if (TargetItem->RefineAdded == 0)
                {
                    GameScene::Scene->ChatDialog->ReceiveChat(StringHelper::formatSimple("Your {0} hasn't been refined so it doesn't need checking.", TargetItem->getFriendlyName()), ChatType::System);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar5' statement was not added since tempVar5 was passed to a method or constructor. Handle memory management manually.
                    return;
                }
                C::CheckRefine *tempVar9 = new C::CheckRefine();
                tempVar9->UniqueID = TargetItem->UniqueID;
                Network::Enqueue(tempVar9);
                break;

            case PanelType::ReplaceWedRing:

                if (TargetItem->Info->Type != ItemType::Ring)
                {
                    GameScene::Scene->ChatDialog->ReceiveChat(StringHelper::formatSimple("{0} isn't a ring.", TargetItem->getFriendlyName()), ChatType::System);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar9' statement was not added since tempVar9 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar5' statement was not added since tempVar5 was passed to a method or constructor. Handle memory management manually.
                    return;
                }

                C::ReplaceWedRing *tempVar10 = new C::ReplaceWedRing();
                tempVar10->UniqueID = TargetItem->UniqueID;
                Network::Enqueue(tempVar10);
                break;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar10' statement was not added since tempVar10 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar9' statement was not added since tempVar9 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar5' statement was not added since tempVar5 was passed to a method or constructor. Handle memory management manually.
        }


        TargetItem = nullptr;
        OldCell->setLocked(false);
        OldCell = nullptr;
    }

    void NPCDropDialog::ItemCell_Click()
    {
        if (OldCell != nullptr)
        {
            OldCell->setLocked(false);
            TargetItem = nullptr;
            OldCell = nullptr;
        }

        if (GameScene::SelectedCell != nullptr && PType == PanelType::Disassemble)
        {
            if (GameScene::SelectedCell->getItem()->Info->Grade != ItemGrade::None && GameScene::SelectedCell->getItem()->Info->Type != ItemType::Awakening)
            {
                TargetItem = GameScene::SelectedCell->getItem();
                OldCell = GameScene::SelectedCell;
                OldCell->setLocked(true);
                GameScene::SelectedCell = nullptr;
                return;
            }
        }

        if (GameScene::SelectedCell != nullptr && PType == PanelType::Downgrade)
        {
            if (GameScene::SelectedCell->getItem()->Awake->GetAwakeLevel() != 0)
            {
                TargetItem = GameScene::SelectedCell->getItem();
                OldCell = GameScene::SelectedCell;
                OldCell->setLocked(true);
                GameScene::SelectedCell = nullptr;
                return;
            }
        }

        if (GameScene::SelectedCell != nullptr && PType == PanelType::Reset)
        {
            if (GameScene::SelectedCell->getItem()->isAdded())
            {
                TargetItem = GameScene::SelectedCell->getItem();
                OldCell = GameScene::SelectedCell;
                OldCell->setLocked(true);
                GameScene::SelectedCell = nullptr;
                return;
            }
        }

        if (GameScene::SelectedCell != nullptr && (PType == PanelType::Disassemble || PType == PanelType::Downgrade || PType == PanelType::Reset))
        {
            GameScene::SelectedCell->setLocked(false);
            GameScene::SelectedCell = nullptr;
            return;
        }

        //////////////////////////////////////

        if (GameScene::SelectedCell == nullptr || GameScene::SelectedCell->getGridType() != MirGridType::Inventory || (PType != PanelType::Sell && PType != PanelType::Consign && GameScene::SelectedCell->getItem() != nullptr && GameScene::SelectedCell->getItem()->Info->Durability == 0))
        {
            return;
        }
        /*
        if (GameScene.SelectedCell.Item != null && (GameScene.SelectedCell.Item.Info.StackSize > 1 && GameScene.SelectedCell.Item.Count > 1))
        {
            MirAmountBox amountBox = new MirAmountBox("Sell Amount:", GameScene.SelectedCell.Item.Image, GameScene.SelectedCell.Item.Count);
    
            amountBox.OKButton.Click += (o, a) =>
            {
                TargetItem = GameScene.SelectedCell.Item.Clone();
                TargetItem.Count = amountBox.Amount;
    
                OldCell = GameScene.SelectedCell;
                OldCell.Locked = true;
                GameScene.SelectedCell = null;
                if (Hold) Confirm();
            };
    
            amountBox.Show();
        }
        else
        {
            TargetItem = GameScene.SelectedCell.Item;
            OldCell = GameScene.SelectedCell;
            OldCell.Locked = true;
            GameScene.SelectedCell = null;
            if (Hold) Confirm();
        }
        */
        TargetItem = GameScene::SelectedCell->getItem();
        OldCell = GameScene::SelectedCell;
        OldCell->setLocked(true);
        GameScene::SelectedCell = nullptr;
        if (Hold)
        {
            Confirm();
        }
    }

    void NPCDropDialog::NPCDropPanel_BeforeDraw(std::any sender, EventArgs *e)
    {
        std::string text;

        HoldButton->setVisible(true);

        setIndex(351);
        setLibrary(Libraries::Prguse2);
        Point tempVar(264, 224);
        setLocation(&tempVar);

        ConfirmButton->setHoverIndex(291);
        ConfirmButton->setIndex(290);
        ConfirmButton->setPressedIndex(292);
        Point tempVar2(114, 62);
        ConfirmButton->setLocation(&tempVar2);

        Point tempVar3(30, 10);
        InfoLabel->setLocation(&tempVar3);

        Point tempVar4(38, 72);
        ItemCell->setLocation(&tempVar4);

        switch (PType)
        {
            case PanelType::Sell:
                text = "Sale: ";
                break;
            case PanelType::Repair:
                text = "Repair: ";
                break;
            case PanelType::SpecialRepair:
                text = "S. Repair: ";
                break;
            case PanelType::Consign:
                InfoLabel->setText("Consignment: ");
                return;
            case PanelType::Disassemble:
                text = "Item will be Destroyed\n\n\n\n\n\n\n\n         ";
                HoldButton->setVisible(false);
                setIndex(711);
                setLibrary(Libraries::Title);
                Point tempVar5(234, 224);
                setLocation(&tempVar5);
                ConfirmButton->setHoverIndex(716);
                ConfirmButton->setIndex(715);
                ConfirmButton->setPressedIndex(717);
                Point tempVar6(62, 190);
                ConfirmButton->setLocation(&tempVar6);
                Point tempVar7(44, 60);
                InfoLabel->setLocation(&tempVar7);
                Point tempVar8(83, 94);
                ItemCell->setLocation(&tempVar8);
                break;
            case PanelType::Downgrade:
                text = "Downgrade: ";
                HoldButton->setVisible(false);
                break;
            case PanelType::Reset:
                text = "Reset: ";
                HoldButton->setVisible(false);
                break;
            case PanelType::Refine:
                text = "Refine: ";
                HoldButton->setVisible(false);
                ConfirmButton->setVisible(true);
                GameScene::Scene->RefineDialog->Show();
                break;
            case PanelType::CheckRefine:
                text = "Check Refine";
                HoldButton->setVisible(false);
                ConfirmButton->setVisible(true);
                break;
            case PanelType::ReplaceWedRing:
                text = "Replace: ";
                HoldButton->setVisible(false);
                ConfirmButton->setVisible(true);
                break;

            default:
                return;

        }

        if (TargetItem != nullptr)
        {

            switch (PType)
            {
                case PanelType::Sell:
                    text += std::to_string(TargetItem->Price() / 2);
                    break;
                case PanelType::Repair:
                    text += std::to_string(TargetItem->RepairPrice() * GameScene::NPCRate);
                    break;
                case PanelType::SpecialRepair:
                    text += std::to_string((TargetItem->RepairPrice() * 3) * GameScene::NPCRate);
                    break;
                case PanelType::Disassemble:
                    text += std::to_string(TargetItem->DisassemblePrice());
                    break;
                case PanelType::Downgrade:
                    text += std::to_string(TargetItem->DowngradePrice());
                    break;
                case PanelType::Reset:
                    text += std::to_string(TargetItem->ResetPrice());
                    break;
                case PanelType::Refine:
                    text += std::to_string((TargetItem->Info->RequiredAmount * 10) * GameScene::NPCRate);
                    break;
                case PanelType::ReplaceWedRing:
                    text += std::to_string((TargetItem->Info->RequiredAmount * 10) * GameScene::NPCRate);
                    break;
                default:
                    return;
            }

            text += " Gold";
        }

        InfoLabel->setText(text);
    }

    void NPCDropDialog::Hide()
    {
        if (OldCell != nullptr)
        {
            OldCell->setLocked(false);
            TargetItem = nullptr;
            OldCell = nullptr;
        }
        setVisible(false);
    }

    void NPCDropDialog::Show()
    {
        Hold = false;
        GameScene::Scene->InventoryDialog->Show();
        setVisible(true);
    }

std::vector<UserItem*> NPCAwakeDialog::Items(7);
std::vector<int> NPCAwakeDialog::ItemsIdx(7);

    NPCAwakeDialog::NPCAwakeDialog()
    {
        setIndex(710);
        setLibrary(Libraries::Title);
        Point tempVar(0, 0);
        setLocation(&tempVar);
        setSort(true);
        setMovable(true);

        GoldLabel = new MirLabel();
        GoldLabel->setAutoSize(true);
        Point tempVar2(112, 354);
        GoldLabel->setLocation(&tempVar2);
        GoldLabel->setParent(this);
        GoldLabel->setNotControl(true);

        NeedItemLabel1 = new MirLabel();
        NeedItemLabel1->setAutoSize(true);
        Point tempVar3(67, 317);
        NeedItemLabel1->setLocation(&tempVar3);
        NeedItemLabel1->setParent(this);
        NeedItemLabel1->setNotControl(true);

        NeedItemLabel2 = new MirLabel();
        NeedItemLabel2->setAutoSize(true);
        Point tempVar4(192, 317);
        NeedItemLabel2->setLocation(&tempVar4);
        NeedItemLabel2->setParent(this);
        NeedItemLabel2->setNotControl(true);

        UpgradeButton = new MirButton();
        UpgradeButton->setHoverIndex(713);
        UpgradeButton->setIndex(712);
        Point tempVar5(115, 391);
        UpgradeButton->setLocation(&tempVar5);
        UpgradeButton->setLibrary(Libraries::Title);
        UpgradeButton->setParent(this);
        UpgradeButton->setPressedIndex(714);
        UpgradeButton->setSound(SoundList::ButtonA);
        UpgradeButton->Click += [&] (o, e)
        {
            Awakening();
        };

        CloseButton = new MirButton();
        CloseButton->setHoverIndex(361);
        CloseButton->setIndex(360);
        Point tempVar6(284, 4);
        CloseButton->setLocation(&tempVar6);
        CloseButton->setLibrary(Libraries::Prguse2);
        CloseButton->setParent(this);
        CloseButton->setPressedIndex(362);
        CloseButton->setSound(SoundList::ButtonA);
        CloseButton->Click += [&] (o, e)
        {
            Hide();
        };

        MirItemCell *tempVar7 = new MirItemCell();
        tempVar7->setBorderColour(Color::Lime);
        tempVar7->setGridType(MirGridType::AwakenItem);
        tempVar7->setLibrary(Libraries::Items);
        tempVar7->setParent(this);
        Point tempVar8(202, 91);
        tempVar7->setLocation(&tempVar8);
        tempVar7->setItemSlot(0);
        ItemCells[0] = tempVar7;
        //ItemCells[0].AfterDraw += (o, e) => ItemCell_AfterDraw();
        //ItemCells[0].Click += (o, e) => ItemCell_Click();

        MirItemCell *tempVar9 = new MirItemCell();
        tempVar9->setBorderColour(Color::Lime);
        tempVar9->setGridType(MirGridType::AwakenItem);
        tempVar9->setLibrary(Libraries::Items);
        tempVar9->setParent(this);
        Point tempVar10(31, 316);
        tempVar9->setLocation(&tempVar10);
        tempVar9->setItemSlot(1);
        tempVar9->setEnabled(false);
        ItemCells[1] = tempVar9;

        MirItemCell *tempVar11 = new MirItemCell();
        tempVar11->setBorderColour(Color::Lime);
        tempVar11->setGridType(MirGridType::AwakenItem);
        tempVar11->setLibrary(Libraries::Items);
        tempVar11->setParent(this);
        Point tempVar12(155, 316);
        tempVar11->setLocation(&tempVar12);
        tempVar11->setItemSlot(2);
        tempVar11->setEnabled(false);
        ItemCells[2] = tempVar11;

        MirItemCell *tempVar13 = new MirItemCell();
        tempVar13->setBorderColour(Color::Lime);
        tempVar13->setGridType(MirGridType::AwakenItem);
        tempVar13->setLibrary(Libraries::Items);
        tempVar13->setParent(this);
        Point tempVar14(175, 199);
        tempVar13->setLocation(&tempVar14);
        tempVar13->setItemSlot(3);
        ItemCells[3] = tempVar13;

        MirItemCell *tempVar15 = new MirItemCell();
        tempVar15->setBorderColour(Color::Lime);
        tempVar15->setGridType(MirGridType::AwakenItem);
        tempVar15->setLibrary(Libraries::Items);
        tempVar15->setParent(this);
        Point tempVar16(230, 199);
        tempVar15->setLocation(&tempVar16);
        tempVar15->setItemSlot(4);
        ItemCells[4] = tempVar15;

        MirItemCell *tempVar17 = new MirItemCell();
        tempVar17->setBorderColour(Color::Lime);
        tempVar17->setGridType(MirGridType::AwakenItem);
        tempVar17->setLibrary(Libraries::Items);
        tempVar17->setParent(this);
        Point tempVar18(175, 256);
        tempVar17->setLocation(&tempVar18);
        tempVar17->setItemSlot(5);
        ItemCells[5] = tempVar17;

        MirItemCell *tempVar19 = new MirItemCell();
        tempVar19->setBorderColour(Color::Lime);
        tempVar19->setGridType(MirGridType::AwakenItem);
        tempVar19->setLibrary(Libraries::Items);
        tempVar19->setParent(this);
        Point tempVar20(230, 256);
        tempVar19->setLocation(&tempVar20);
        tempVar19->setItemSlot(6);
        ItemCells[6] = tempVar19;

        SelectAwakeType = new MirDropDownBox();
        SelectAwakeType->setParent(this);
        Point tempVar21(35, 141);
        SelectAwakeType->setLocation(&tempVar21);
        Size tempVar22(109, 14);
        SelectAwakeType->setSize(&tempVar22);
        SelectAwakeType->setForeColour(Color::White);
        SelectAwakeType->setVisible(true);
        SelectAwakeType->setEnabled(true);
        SelectAwakeType->ValueChanged->addListener([&] (o, e)
        {
            OnAwakeTypeSelect(SelectAwakeType->_WantedIndex);
        });

        delete tempVar19;
        delete tempVar17;
        delete tempVar15;
        delete tempVar13;
        delete tempVar11;
        delete tempVar9;
        delete tempVar7;
    }

    void NPCAwakeDialog::ItemCellClear()
    {
        if (ItemCells[1]->getItem() != nullptr)
        {
            ItemCells[1]->setItem(nullptr);
        }
        if (ItemCells[2]->getItem() != nullptr)
        {
            ItemCells[2]->setItem(nullptr);
        }


        NeedItemLabel2->setText("");
        NeedItemLabel1->setText("");
        GoldLabel->setText("");
    }

    void NPCAwakeDialog::ItemCell_Click()
    {
        ItemCellClear();
        SelectAwakeType->getItems().clear();

        if (Items[0] == nullptr)
        {
            SelectAwakeType->getItems().push_back("Select Upgrade Item.");
            SelectAwakeType->setSelectedIndex(SelectAwakeType->getItems().size() - 1);
            CurrentAwakeType = AwakeType::None;
        }
        else
        {
            if (Items[0]->Awake.GetAwakeLevel() == 0)
            {
                SelectAwakeType->getItems().push_back("Select Upgrade Type.");
                if (Items[0]->Info->Type == ItemType::Weapon)
                {
                    SelectAwakeType->getItems().push_back("Bravery Glyph");
                    SelectAwakeType->getItems().push_back("Magic Glyph");
                    SelectAwakeType->getItems().push_back("Soul Glyph");
                }
                else if (Items[0]->Info->Type == ItemType::Helmet)
                {
                    SelectAwakeType->getItems().push_back("Protection Glyph");
                    SelectAwakeType->getItems().push_back("EvilSlayer Glyph");
                }
                else
                {
                    SelectAwakeType->getItems().push_back("Body Glyph");
                }
            }
            else
            {
                SelectAwakeType->getItems().push_back(getAwakeTypeText(Items[0]->Awake.Type));
                if (CurrentAwakeType != Items[0]->Awake.Type)
                {
                    CurrentAwakeType = Items[0]->Awake.Type;
                    OnAwakeTypeSelect(0);
                }
            }
        }
    }

    std::string NPCAwakeDialog::getAwakeTypeText(AwakeType type)
    {
        std::string typeName = "";
        switch (type)
        {
            case AwakeType::DC:
                typeName = "Bravery Glyph";
                break;
            case AwakeType::MC:
                typeName = "Magic Glyph";
                break;
            case AwakeType::SC:
                typeName = "Soul Glyph";
                break;
            case AwakeType::AC:
                typeName = "Protection Glyph";
                break;
            case AwakeType::MAC:
                typeName = "EvilSlayer Glyph";
                break;
            case AwakeType::HPMP:
                typeName = "Body Glyph";
                break;
            default:
                typeName = "Select Upgrade Item.";
                break;
        }
        return typeName;
    }

    AwakeType NPCAwakeDialog::getAwakeType(const std::string &typeName)
    {
        AwakeType type = AwakeType::None;
//C# TO C++ CONVERTER NOTE: The following 'switch' operated on a string and was converted to C++ 'if-else' logic:
//        switch (typeName)
//ORIGINAL LINE: case "Bravery Glyph":
        if (typeName == "Bravery Glyph")
        {
                type = AwakeType::DC;
        }
//ORIGINAL LINE: case "Magic Glyph":
        else if (typeName == "Magic Glyph")
        {
                type = AwakeType::MC;
        }
//ORIGINAL LINE: case "Soul Glyph":
        else if (typeName == "Soul Glyph")
        {
                type = AwakeType::SC;
        }
//ORIGINAL LINE: case "Protection Glyph":
        else if (typeName == "Protection Glyph")
        {
                type = AwakeType::AC;
        }
//ORIGINAL LINE: case "EvilSlayer Glyph":
        else if (typeName == "EvilSlayer Glyph")
        {
                type = AwakeType::MAC;
        }
//ORIGINAL LINE: case "Body Glyph":
        else if (typeName == "Body Glyph")
        {
                type = AwakeType::HPMP;
        }
        else
        {
                type = AwakeType::None;
        }

        return type;
    }

    void NPCAwakeDialog::OnAwakeTypeSelect(int Index)
    {
        SelectAwakeType->setSelectedIndex(Index);

        AwakeType type = getAwakeType(SelectAwakeType->getItems()[SelectAwakeType->getSelectedIndex()]);
        CurrentAwakeType = type;
        if (type != AwakeType::None)
        {
            C::AwakeningNeedMaterials *tempVar = new C::AwakeningNeedMaterials();
            tempVar->UniqueID = Items[0]->UniqueID;
            tempVar->Type = type;
            Network::Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
        }
    }

    void NPCAwakeDialog::setNeedItems(std::vector<ItemInfo*> &Materials, std::vector<unsigned char> &MaterialsCount)
    {
        if (MaterialsCount[0] != 0)
        {
            UserItem tempVar(Materials[0]);
            ItemCells[1]->setItem(&tempVar);
            ItemCells[1]->getItem()->Count = MaterialsCount[0];
            NeedItemLabel1->setText(Regex::Replace(ItemCells[1]->getItem().Info->Name, R"([\d-])", "") + "\nQuantity: " + std::to_string(MaterialsCount[0]));
        }
        else
        {
            ItemCells[1]->setItem(nullptr);
            NeedItemLabel1->setText("");
        }

        if (MaterialsCount[1] != 0)
        {
            UserItem tempVar2(Materials[1]);
            ItemCells[2]->setItem(&tempVar2);
            ItemCells[2]->getItem()->Count = MaterialsCount[1];
            NeedItemLabel2->setText(Regex::Replace(ItemCells[2]->getItem().Info->Name, R"([\d-])", "") + "\nQuantity:" + std::to_string(MaterialsCount[1]));
        }
        else
        {
            ItemCells[2]->setItem(nullptr);
            NeedItemLabel2->setText("");
        }

        if (ItemCells[0]->getItem() != nullptr)
        {
//C# TO C++ CONVERTER TODO TASK: There is no C++ equivalent to 'ToString':
            GoldLabel->setText(ItemCells[0]->getItem().AwakeningPrice().ToString());
        }
    }

    bool NPCAwakeDialog::CheckNeedMaterials()
    {
        int maxEqual = (Items[1] == nullptr || Items[2] == nullptr) ? 1 : 2;
        int equal = 0;
        for (int i = 1; i < 3; i++)
        {
            if (Items[i] == nullptr)
            {
                continue;
            }
            for (int j = 3; j < 5; j++)
            {
                if (Items[j] == nullptr)
                {
                    continue;
                }
                if (Items[i]->Info->Name == Items[j]->Info->Name && Items[i]->Count <= Items[j]->Count)
                {
                    equal++;
                }
            }
        }
        return equal >= maxEqual;
    }

    void NPCAwakeDialog::Awakening()
    {
        if (CheckNeedMaterials())
        {
            AwakeType type = getAwakeType(SelectAwakeType->getItems()[SelectAwakeType->getSelectedIndex()]);

            if (type != AwakeType::None)
            {
                C::Awakening *tempVar = new C::Awakening();
                tempVar->UniqueID = Items[0]->UniqueID;
                tempVar->Type = type;
                Network::Enqueue(tempVar);
                MapControl::setAwakeningAction(true);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            }
        }
    }

    void NPCAwakeDialog::Hide()
    {
        for (auto item : ItemCells)
        {
            if (item->getItem() != nullptr)
            {
                C::AwakeningLockedItem *tempVar = new C::AwakeningLockedItem();
                tempVar->UniqueID = item->getItem()->UniqueID;
                tempVar->Locked = false;
                Network::Enqueue(tempVar);
                item->setItem(nullptr);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            }
        }

        for (int i = 0; i < ItemsIdx.size(); i++)
        {
            ItemsIdx[i] = 0;
        }

        ItemCell_Click();
        setVisible(false);
    }

    void NPCAwakeDialog::Show()
    {
        setVisible(true);

        Point tempVar(getSize()->Width + 5, 0);
        GameScene::Scene->InventoryDialog->setLocation(&tempVar);
        GameScene::Scene->InventoryDialog->Show();
    }

    int CraftDialog::getTotalCount()
    {
        return _toolCount + _ingredientCount;
    }

std::vector<UserItem*> CraftDialog::Slots(getTotalCount());
std::vector<UserItem*> CraftDialog::ShadowItems(getTotalCount());

    CraftDialog::CraftDialog()
    {
        setIndex(1109);
        setLibrary(Libraries::Prguse);
        Point tempVar(0, 0);
        setLocation(&tempVar);
        setSort(true);
        BeforeDraw += CraftDialog_BeforeDraw;
        setMovable(true);

        RecipeLabel = new MirLabel();
        RecipeLabel->setAutoSize(true);
        RecipeLabel->setParent(this);
        Point tempVar2(22, 5);
        RecipeLabel->setLocation(&tempVar2);
        System::Drawing::Font tempVar3(Settings::FontName, 10.0F, FontStyle::Bold);
        RecipeLabel->setFont(&tempVar3);
        RecipeLabel->setForeColour(Color::BurlyWood);
        RecipeLabel->setVisible(true);
        RecipeLabel->setNotControl(true);

        PossibilityLabel = new MirLabel();
        PossibilityLabel->setAutoSize(true);
        PossibilityLabel->setForeColour(Color::White);
        PossibilityLabel->setParent(this);
        Point tempVar4(10, 135);
        PossibilityLabel->setLocation(&tempVar4);
        System::Drawing::Font tempVar5(Settings::FontName, 8.0F);
        PossibilityLabel->setFont(&tempVar5);
        PossibilityLabel->setVisible(true);
        PossibilityLabel->setNotControl(true);

        GoldLabel = new MirLabel();
        GoldLabel->setAutoSize(true);
        GoldLabel->setForeColour(Color::White);
        GoldLabel->setParent(this);
        Point tempVar6(30, 190);
        GoldLabel->setLocation(&tempVar6);
        System::Drawing::Font tempVar7(Settings::FontName, 8.0F);
        GoldLabel->setFont(&tempVar7);
        GoldLabel->setVisible(true);
        GoldLabel->setNotControl(true);

        Grid = std::vector<MirItemCell*>(getTotalCount());
        for (int x = 0; x < getTotalCount(); x++)
        {
            if (x >= _toolCount)
            {
                MirItemCell *tempVar8 = new MirItemCell();
                tempVar8->setItemSlot(x);
                tempVar8->setGridType(MirGridType::Craft);
                tempVar8->setLibrary(Libraries::Items);
                tempVar8->setParent(this);
                Size tempVar9(35, 32);
                tempVar8->setSize(&tempVar9);
                Point tempVar10(((x - _toolCount) * 40) + 52, 86);
                tempVar8->setLocation(&tempVar10);
                tempVar8->setBorder(true);
                tempVar8->setBorderColour(Color::Lime);
                Grid[x] = tempVar8;

                delete tempVar8;
            }
            else
            {
                MirItemCell *tempVar11 = new MirItemCell();
                tempVar11->setItemSlot(x);
                tempVar11->setGridType(MirGridType::Craft);
                tempVar11->setLibrary(Libraries::Items);
                tempVar11->setParent(this);
                Size tempVar12(35, 32);
                tempVar11->setSize(&tempVar12);
                Point tempVar13((x * 44) + 108, 44);
                tempVar11->setLocation(&tempVar13);
                tempVar11->setBorder(true);
                tempVar11->setBorderColour(Color::Lime);
                Grid[x] = tempVar11;

                delete tempVar11;
            }

            Grid[x]->Click += Grid_Click;
        }

        CloseButton = new MirButton();
        CloseButton->setIndex(360);
        CloseButton->setHoverIndex(361);
        CloseButton->setPressedIndex(362);
        Point tempVar14(312, 3);
        CloseButton->setLocation(&tempVar14);
        CloseButton->setLibrary(Libraries::Prguse2);
        CloseButton->setParent(this);
        CloseButton->setSound(SoundList::ButtonA);
        CloseButton->Click += [&] (o, e)
        {
            Hide();
        };

        AutoFillButton = new MirButton();
        AutoFillButton->setHoverIndex(181);
        AutoFillButton->setIndex(180);
        Point tempVar15(165, 185);
        AutoFillButton->setLocation(&tempVar15);
        AutoFillButton->setLibrary(Libraries::Title);
        AutoFillButton->setParent(this);
        AutoFillButton->setPressedIndex(182);
        AutoFillButton->setSound(SoundList::ButtonA);
        AutoFillButton->Click += [&] (o, e)
        {
            AutoFill();
        };

        CraftButton = new MirButton();
        CraftButton->setHoverIndex(337);
        CraftButton->setIndex(336);
        Point tempVar16(215, 185);
        CraftButton->setLocation(&tempVar16);
        CraftButton->setLibrary(Libraries::Title);
        CraftButton->setParent(this);
        CraftButton->setPressedIndex(338);
        CraftButton->setSound(SoundList::ButtonA);
        CraftButton->setGrayScale(true);
        CraftButton->setEnabled(false);
        CraftButton->Click += [&] (o, e)
        {
            CraftItem();
        };
    }

    void CraftDialog::CraftDialog_BeforeDraw(std::any sender, EventArgs *e)
    {
        if (!GameScene::Scene->InventoryDialog->getVisible())
        {
            Hide();
            return;
        }
    }

    void CraftDialog::Grid_Click(std::any sender, EventArgs *e)
    {
        MirItemCell *cell = std::any_cast<MirItemCell*>(sender);

        if (cell == nullptr || cell->getShadowItem() == nullptr)
        {
            return;
        }

        if (GameScene::SelectedCell == nullptr || GameScene::SelectedCell->getGridType() != MirGridType::Inventory || GameScene::SelectedCell->getLocked())
        {
            return;
        }

        if (GameScene::SelectedCell->getItem()->Info != cell->getShadowItem()->Info || cell->getItem() != nullptr)
        {
            return;
        }

        if (cell->getItemSlot() >= _toolCount)
        {
            if (GameScene::SelectedCell->getItem()->Count < cell->getShadowItem()->Count)
            {
                return;
            }

            if (cell->getShadowItem()->CurrentDura < cell->getShadowItem()->MaxDura && GameScene::SelectedCell->getItem()->CurrentDura < cell->getShadowItem()->CurrentDura)
            {
                return;
            }
        }
        else
        {
            if (GameScene::SelectedCell->getItem()->CurrentDura < 1000)
            {
                return;
            }
        }

        cell->setItem(GameScene::SelectedCell->getItem());

        Selected.emplace(GameScene::SelectedCell, GameScene::SelectedCell->getItem()->UniqueID);
        GameScene::SelectedCell->setLocked(true);
        GameScene::SelectedCell = nullptr;

        RefreshCraftCells(RecipeItem);
    }

    void CraftDialog::Hide()
    {
        if (!getVisible())
        {
            return;
        }

        setVisible(false);

        ResetCells();
    }

    void CraftDialog::Show()
    {
        setVisible(true);

        Point tempVar(GameScene::Scene->InventoryDialog->getLocation()->X - 12, GameScene::Scene->InventoryDialog->getLocation()->Y + 236);
        setLocation(&tempVar);
    }

    void CraftDialog::AutoFill()
    {
        ResetCells(false);

        if (RecipeItem == nullptr)
        {
            return;
        }

        std::vector<int> usedSlots;

        int j = 0;
        for (auto tool : *Recipe->Tools)
        {
            for (int i = 0; i < UserObject::User->Inventory.size(); i++)
            {
                if (std::find(usedSlots.begin(), usedSlots.end(), i) != usedSlots.end())
                {
                    continue;
                }

                auto slot = UserObject::User->Inventory[i];

                if (slot == nullptr || tool->Info->Index != slot->Info->Index || slot->CurrentDura < 1000)
                {
                    continue;
                }

                auto cell = GameScene::Scene->InventoryDialog->GetCell(slot->UniqueID);

                if (cell->getLocked())
                {
                    continue;
                }

                Selected.emplace(cell, cell->getItem()->UniqueID);
                cell->setLocked(true);

                Grid[j]->setItem(cell->getItem());
                break;
            }

            j++;
        }

        j = 3;
        for (auto ingredient : *Recipe->Ingredients)
        {
            for (int i = 0; i < UserObject::User->Inventory.size(); i++)
            {
                if (std::find(usedSlots.begin(), usedSlots.end(), i) != usedSlots.end())
                {
                    continue;
                }

                auto slot = UserObject::User->Inventory[i];

                if (slot == nullptr || ingredient->Info->Index != slot->Info->Index)
                {
                    continue;
                }
                if (slot->Count < ingredient->Count)
                {
                    continue;
                }
                if (ingredient->CurrentDura < ingredient->MaxDura && slot->CurrentDura < ingredient->CurrentDura)
                {
                    continue;
                }

                auto cell = GameScene::Scene->InventoryDialog->GetCell(slot->UniqueID);

                if (cell->getLocked())
                {
                    continue;
                }

                Selected.emplace(cell, cell->getItem()->UniqueID);
                cell->setLocked(true);

                Grid[j]->setItem(cell->getItem());
                break;
            }

            j++;
        }

        RefreshCraftCells(RecipeItem);
    }

    void CraftDialog::CraftItem()
    {
        if (RecipeItem == nullptr)
        {
            return;
        }

        if (Selected.size() < Recipe->Tools.size() + Recipe->Ingredients.size())
        {
            return;
        }

        unsigned short max = 99;

        //Max quantity based on available ingredients/tools
        for (int i = 0; i < Grid.size(); i++)
        {
            if (Grid[i] == nullptr || Grid[i]->getItem() == nullptr)
            {
                continue;
            }

            unsigned short temp = 0;
            if (i >= _toolCount)
            {
                temp = static_cast<unsigned short>(Grid[i]->getItem()->Count / Grid[i]->getShadowItem()->Count);
            }
            else
            {
                temp = static_cast<unsigned short>(std::floor(Grid[i]->getItem().CurrentDura / 1000));
            }

            if (temp < max)
            {
                max = temp;
            }
        }

        if (max > (RecipeItem->Info->StackSize / RecipeItem->Count))
        {
            max = static_cast<unsigned short>(RecipeItem->Info->StackSize / RecipeItem->Count);
        }

        //TODO - Check Max slots spare against slots to be used (stacksize/quantity)
        //TODO - GetMaxItemGain

        if (RecipeItem->getWeight() > (MapObject::User->Stats[Stat::BagWeight] - MapObject::User->CurrentBagWeight))
        {
            GameScene::Scene->ChatDialog->ReceiveChat("You do not have enough weight.", ChatType::System);
            return;
        }

        if (Recipe->Gold > GameScene::Gold)
        {
            GameScene::Scene->ChatDialog->ReceiveChat("You do not have enough gold.", ChatType::System);
            return;
        }

        if (max > 1)
        {
            MirAmountBox *amountBox = new MirAmountBox("Craft Amount:", RecipeItem->Info->Image, max, 0, max);

            amountBox->OKButton->Click += [&] (o, e)
            {
                if (amountBox->Amount > 0)
                {
                    if (!HasCraftItems(static_cast<unsigned short>(amountBox->Amount)))
                    {
                        GameScene::Scene->ChatDialog->ReceiveChat("You do not have the required tools or ingredients.", ChatType::System);
                        return;
                    }
    
                    C::CraftItem<unsigned short> tempVar(amountBox->Amount);
                    Network::Enqueue(&tempVar, Slots = Selected.Select([&] (std::any x)
                    {
                    x::Key->ItemSlot;
                    })->ToArray() });
                }
            };

            amountBox->Show();

            delete amountBox;
        }
        else
        {
            Network::Enqueue(new C::CraftItem { UniqueID = RecipeItem->UniqueID, Count = 1, Slots = Selected.Select([&] (std::any x)
            {
                x::Key->ItemSlot;
            })->ToArray() });
        }
    }

    bool CraftDialog::HasCraftItems(unsigned short count)
    {
        for (int i = 0; i < Grid.size(); i++)
        {
            if (Grid[i]->getShadowItem() == nullptr)
            {
                continue;
            }

            if (i >= _toolCount)
            {
                if (Grid[i]->getItem() == nullptr || Grid[i]->getItem()->Count < (Grid[i]->getShadowItem()->Count * count))
                {
                    return false;
                }
            }
            else
            {
                if (Grid[i]->getItem() == nullptr || static_cast<unsigned int>(std::floor(Grid[i]->getItem().CurrentDura / 1000)) < count)
                {
                    return false;
                }
            }
        }

        return true;
    }

    void CraftDialog::ResetCells(bool clearRecipe)
    {
        if (clearRecipe)
        {
            RecipeItem = nullptr;
        }

        for (int j = 0; j < Grid.size(); j++)
        {
            Slots[j] = nullptr;
            ShadowItems[j] = nullptr;
        }

        for (auto key : Selected)
        {
            key->setLocked(false);
        }

        Selected.clear();
    }

    MirItemCell *CraftDialog::GetCell(unsigned long long id)
    {
        for (int i = 0; i < Grid.size(); i++)
        {
            if (Grid[i]->getItem() == nullptr || Grid[i]->getItem().UniqueID != id)
            {
                continue;
            }
            return Grid[i];
        }

        return nullptr;
    }

    void CraftDialog::UpdateCraftCells()
    {
        std::vector<MirItemCell*> invalidCells;

        for (auto key : Selected)
        {
            MirItemCell *cell = key;
            unsigned long long oldItem = Selected[key];

            if (cell->getItem() == nullptr || cell->getItem()->UniqueID != oldItem || (cell->getItem()->MaxDura > 1000 && cell->getItem()->CurrentDura < 1000))
            {
                MirItemCell *gridCell = GetCell(oldItem);

                if (gridCell != nullptr)
                {
                    gridCell->setItem(nullptr);
                }
                cell->setLocked(false);

                invalidCells.push_back(key);
            }
        }

        for (auto cell : invalidCells)
        {
            Selected.erase(cell);
        }

        RefreshCraftCells(RecipeItem);
    }

    void CraftDialog::RefreshCraftCells(UserItem *selectedItem)
    {
        RecipeItem = selectedItem;

        CraftButton->setEnabled(true);
        CraftButton->setGrayScale(false);

        Recipe = GameScene::RecipeInfoList.SingleOrDefault([&] (std::any x)
        {
            return x::Item->ItemIndex == selectedItem->ItemIndex;
        });

        RecipeLabel->setText(Recipe->Item->getFriendlyName());
        PossibilityLabel->setText((UserObject::User->Stats[Stat::CraftRatePercent] > 0 ? StringHelper::formatSimple("{0}% (+{1}%)", std::min(100, Recipe->Chance + UserObject::User->Stats[Stat::CraftRatePercent]), UserObject::User->Stats[Stat::CraftRatePercent]) : StringHelper::formatSimple("{0}%", Recipe->Chance)) + " Chance of Success");
//C# TO C++ CONVERTER TODO TASK: There is no C++ equivalent to 'ToString':
        GoldLabel->setText(Recipe->Gold.ToString("###,###,##0"));

        for (int i = 0; i < Slots.size(); i++)
        {
            bool need;

            if (i >= _toolCount)
            {
                if ((i - _toolCount) >= Recipe->Ingredients.size())
                {
                    continue;
                }

                ShadowItems[i] = Recipe->Ingredients[i - _toolCount];
                need = Grid[i]->getItem() == nullptr || Grid[i]->getItem()->Count < Grid[i]->getShadowItem()->Count;
            }
            else
            {
                if (i >= Recipe->Tools.size())
                {
                    continue;
                }

                ShadowItems[i] = Recipe->Tools[i];
                need = Grid[i]->getItem() == nullptr || Grid[i]->getItem()->Count < Grid[i]->getShadowItem()->Count;
            }

            if (need)
            {
                CraftButton->setEnabled(false);
                CraftButton->setGrayScale(true);
            }
        }
    }

    RefineDialog::RefineDialog()
    {
        setIndex(1002);
        setLibrary(Libraries::Prguse);
        Point tempVar(0, 225);
        setLocation(&tempVar);
        setSort(true);

        MirImageControl *TitleLabel = new MirImageControl();
        TitleLabel->setIndex(18);
        TitleLabel->setLibrary(Libraries::Title);
        Point tempVar2(28, 8);
        TitleLabel->setLocation(&tempVar2);
        TitleLabel->setParent(this);


        Grid = std::vector<MirItemCell*>(4 * 4);
        for (int x = 0; x < 4; x++)
        {
            for (int y = 0; y < 4; y++)
            {
                int idx = 4 * y + x;
                MirItemCell *tempVar3 = new MirItemCell();
                tempVar3->setItemSlot(idx);
                tempVar3->setGridType(MirGridType::Refine);
                tempVar3->setLibrary(Libraries::Items);
                tempVar3->setParent(this);
                Size tempVar4(34, 32);
                tempVar3->setSize(&tempVar4);
                Point tempVar5(x * 34 + 12 + x, y * 32 + 37 + y);
                tempVar3->setLocation(&tempVar5);
                Grid[idx] = tempVar3;

                delete tempVar3;
            }
        }

        delete TitleLabel;
    }

    void RefineDialog::Hide()
    {
        setVisible(false);
        RefineCancel();
    }

    void RefineDialog::RefineCancel()
    {
        C::RefineCancel tempVar();
        Network::Enqueue(&tempVar);
    }

    void RefineDialog::RefineReset()
    {
        for (int i = 0; i < Grid.size(); i++)
        {
            Grid[i]->setItem(nullptr);
        }
    }

    MirItemCell *RefineDialog::GetCell(unsigned long long id)
    {
        for (int i = 0; i < Grid.size(); i++)
        {
            if (Grid[i]->getItem() == nullptr || Grid[i]->getItem().UniqueID != id)
            {
                continue;
            }
            return Grid[i];
        }
        return nullptr;
    }

    StorageDialog::StorageDialog()
    {
        setIndex(586);
        setLibrary(Libraries::Prguse);
        Point tempVar(0, 0);
        setLocation(&tempVar);
        setSort(true);

        MirImageControl *TitleLabel = new MirImageControl();
        TitleLabel->setIndex(0);
        TitleLabel->setLibrary(Libraries::Title);
        Point tempVar2(18, 8);
        TitleLabel->setLocation(&tempVar2);
        TitleLabel->setParent(this);

        LockedPage = new MirImageControl();
        LockedPage->setIndex(2443);
        LockedPage->setLibrary(Libraries::Prguse);
        Point tempVar3(8, 59);
        LockedPage->setLocation(&tempVar3);
        LockedPage->setParent(this);
        LockedPage->setVisible(false);

        Storage1Button = new MirButton();
        Storage1Button->setHoverIndex(743);
        Storage1Button->setIndex(743);
        Point tempVar4(8, 36);
        Storage1Button->setLocation(&tempVar4);
        Storage1Button->setLibrary(Libraries::Title);
        Storage1Button->setParent(this);
        Storage1Button->setPressedIndex(744);
        Storage1Button->setSound(SoundList::ButtonA);
        Storage1Button->Click += [&] (o, e)
        {
            RefreshStorage1();
        };

        Storage2Button = new MirButton();
        Storage2Button->setHoverIndex(746);
        Storage2Button->setIndex(746);
        Point tempVar5(80, 36);
        Storage2Button->setLocation(&tempVar5);
        Storage2Button->setLibrary(Libraries::Title);
        Storage2Button->setParent(this);
        Storage2Button->setPressedIndex(746);
        Storage2Button->setSound(SoundList::ButtonA);
        Storage2Button->setVisible(true);
        Storage2Button->Click += [&] (o, e)
        {
            RefreshStorage2();
        };
        RentButton = new MirButton();
        RentButton->setIndex(483);
        RentButton->setHoverIndex(484);
        RentButton->setPressedIndex(485);
        RentButton->setLibrary(Libraries::Title);
        Point tempVar6(283, 33);
        RentButton->setLocation(&tempVar6);
        RentButton->setParent(this);
        RentButton->setSound(SoundList::ButtonA);
        RentButton->setVisible(true);
        RentButton->Click += [&] (o, e)
        {
            MirMessageBox *messageBox;
    
            if (GameScene::getUser()->HasExpandedStorage)
            {
                messageBox = new MirMessageBox(GameLanguage::ExtendYourRentalPeriod, MirMessageBoxButtons::OKCancel);
            }
            else
            {
                messageBox = new MirMessageBox(GameLanguage::ExtraStorage, MirMessageBoxButtons::OKCancel);
            }
    
            messageBox->OKButton->Click += [&] (o1, a)
            {
                    C::Chat *tempVar7 = new C::Chat();
                    tempVar7->Message = "@ADDSTORAGE";
                    Network::Enqueue(tempVar7);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar7' statement was not added since tempVar7 was passed to a method or constructor. Handle memory management manually.
            };
            messageBox->Show();

            delete messageBox;
        };

        ProtectButton = new MirButton();
        ProtectButton->setHoverIndex(114);
        ProtectButton->setIndex(113);
        Point tempVar8(328, 33);
        ProtectButton->setLocation(&tempVar8);
        ProtectButton->setLibrary(Libraries::Title);
        ProtectButton->setParent(this);
        ProtectButton->setPressedIndex(115);
        ProtectButton->setSound(SoundList::ButtonA);
        ProtectButton->setVisible(true);
        CloseButton = new MirButton();
        CloseButton->setHoverIndex(361);
        CloseButton->setIndex(360);
        Point tempVar9(363, 3);
        CloseButton->setLocation(&tempVar9);
        CloseButton->setLibrary(Libraries::Prguse2);
        CloseButton->setParent(this);
        CloseButton->setPressedIndex(362);
        CloseButton->setSound(SoundList::ButtonA);
        CloseButton->Click += [&] (o, e)
        {
            Hide();
        };

        RentalLabel = new MirLabel();
        RentalLabel->setParent(this);
        Point tempVar10(40, 322);
        RentalLabel->setLocation(&tempVar10);
        RentalLabel->setAutoSize(true);
        RentalLabel->setDrawFormat(TextFormatFlags::HorizontalCenter | TextFormatFlags::VerticalCenter);
        RentalLabel->setNotControl(true);
        RentalLabel->setText(GameLanguage::ExpandedStorageLocked);
        RentalLabel->setForeColour(Color::Red);

        Grid = std::vector<MirItemCell*>(10 * 16);

        for (int x = 0; x < 10; x++)
        {
            for (int y = 0; y < 16; y++)
            {
                int idx = 10 * y + x;

                MirItemCell *tempVar11 = new MirItemCell();
                tempVar11->setItemSlot(idx);
                tempVar11->setGridType(MirGridType::Storage);
                tempVar11->setLibrary(Libraries::Items);
                tempVar11->setParent(this);
                Point tempVar12(x * 36 + 9 + x, y % 8 * 32 + 60 + y % 8);
                tempVar11->setLocation(&tempVar12);
                Grid[idx] = tempVar11;

                if (idx >= 80)
                {
                    Grid[idx]->setVisible(false);
                }

                delete tempVar11;
            }
        }

        delete TitleLabel;
    }

    void StorageDialog::Show()
    {
        GameScene::Scene->InventoryDialog->Show();
        RefreshStorage1();

        setVisible(true);
    }

    void StorageDialog::RefreshStorage1()
    {
        if (GameScene::getUser() == nullptr)
        {
            return;
        }

        Storage1Button->setIndex(743);
        Storage1Button->setHoverIndex(743);
        Storage2Button->setIndex(746);
        Storage2Button->setHoverIndex(746);

        for (auto grid : Grid)
        {
            if (grid->getItemSlot() < 80)
            {
                grid->setVisible(true);
            }
            else
            {
                grid->setVisible(false);
            }
        }

        RentButton->setVisible(false);
        LockedPage->setVisible(false);
        RentalLabel->setVisible(false);
    }

    void StorageDialog::RefreshStorage2()
    {
        if (GameScene::getUser() == nullptr)
        {
            return;
        }

        Storage1Button->setIndex(744);
        Storage1Button->setHoverIndex(744);
        Storage2Button->setIndex(745);
        Storage2Button->setHoverIndex(745);

        RentalLabel->setVisible(true);

        if (GameScene::getUser()->HasExpandedStorage)
        {
            RentButton->setVisible(true);
            LockedPage->setVisible(false);
//C# TO C++ CONVERTER TODO TASK: There is no C++ equivalent to 'ToString':
            RentalLabel->setText(GameLanguage::ExpandedStorageExpiresOn + GameScene::getUser()->ExpandedStorageExpiryTime.ToString());
            RentalLabel->setForeColour(Color::White);
        }
        else
        {
            RentalLabel->setText(GameLanguage::ExpandedStorageLocked);
            RentalLabel->setForeColour(Color::Red);
            RentButton->setVisible(true);
            LockedPage->setVisible(true);
        }

        for (auto grid : Grid)
        {
            if (grid->getItemSlot() < 80 || !GameScene::getUser()->HasExpandedStorage)
            {
                grid->setVisible(false);
            }
            else
            {
                grid->setVisible(true);
            }
        }
    }

    MirItemCell *StorageDialog::GetCell(unsigned long long id)
    {
        for (int i = 0; i < Grid.size(); i++)
        {
            if (Grid[i]->getItem() == nullptr || Grid[i]->getItem().UniqueID != id)
            {
                continue;
            }
            return Grid[i];
        }
        return nullptr;
    }
}
